/**
 * 
 * @returns form表单组件
 */
function dynamicForm() {
  return {
    restrict: 'E',
    scope: {
      fields: '=',
      labelWidth: '@',
      submit: '&'
    },
    templateUrl: './component/form-template/form-template.html',
    link: function (scope, element, attrs) {
      scope.fields.forEach(function (d) {
        scope.myForm[d.name] = {
          $setValidity: angular.noop,
          $setDirty: angular.noop,
          $error: {},
          $invalid: false
        };
      })

      // 可以在这里进行额外的数据绑定或DOM操作
      scope.onSubmit = function () {
        const errorNodes = element[0].querySelectorAll('.el-form-item__error');
        let hasError = false;
        let form = {}

        for (let i = 0; i < scope.fields.length; i++) {
          let field = scope.fields[i];
          let errorNode = errorNodes[i];
          let formControl = scope.myForm[field.name];

          // 初始化状态和错误信息
          formControl.$invalid = false;
          errorNode.textContent = '';
          form[field.name] = field.value

          // 执行校验逻辑
          if ((!field.value || !field.value.length) && field.required) {
            formControl.$invalid = true;
            errorNode.textContent = '不能为空!';
            hasError = true;
          } else if ((typeof field.customValidationFunction === 'function') && field.required) {
            let validationMessage = field.customValidationFunction(field.value);
            if (validationMessage) {
              formControl.$invalid = true;
              errorNode.textContent = validationMessage;
              hasError = true;
            }
          }
        }

        if (!hasError) {
          scope.submit({ form: form });
        }
      }
    }
  };
}

/**
 * 
 * @returns 单选框组组件
 */
function radioGroup() {
  return {
    restrict: 'E',
    scope: {
      options: '=',
      ngModel: '=',
      disabled: '@'
    },
    templateUrl: './component/el-radio-group/radioGroup.html',
    link: function (scope, element, attrs) {
      // 监听ngModel的变化
      scope.$watch('ngModel', function (newValue, oldValue) {
        if (newValue !== oldValue) {
          updateSelected(newValue);
        }
      });

      // 更新选中的单选框
      function updateSelected(selectedValue) {
        scope.options.forEach(function (option) {
          option.selected = option.value === selectedValue;
        });
      }

      // 初始化选中的单选框
      updateSelected(scope.ngModel || null);

      // 处理单选框变化事件
      scope.selectRadio = function (option) {
        scope.ngModel = option.value;
      };
    }
  };
}

/**
 * 
 * @returns 复选框组组件
 */
function checkboxGroup() {
  return {
    restrict: 'E', // 指令作为元素使用
    scope: {
      options: '=', // 绑定选项数组
      ngModel: '=', // 双向绑定选中的值
      disabled: '@'
    },
    templateUrl: './component/el-checkbox-group/checkboxGroup.html', // 指令的HTML模板
    link: function (scope, element, attrs) {
      // 监听ngModel的变化，以便在外部更改时更新视图
      scope.$watch('ngModel', function (newValue, oldValue) {
        if (newValue !== oldValue) {
          updateSelected(newValue);
        }
      }, true); // 使用true进行深度监听

      // 更新选中的复选框
      function updateSelected(selectedValues) {
        scope.options.forEach(function (option) {
          option.checked = selectedValues.indexOf(option.value) !== -1;
        });
      }

      // 初始化选中的复选框
      updateSelected(scope.ngModel || []);

      // 处理复选框变化事件
      scope.toggleCheckbox = function (option) {
        var index = scope.ngModel.indexOf(option.value);
        if (index !== -1) {
          scope.ngModel.splice(index, 1);
        } else {
          scope.ngModel.push(option.value);
        }
        // 触发ngModel的$watch以更新父作用域（如果需要）
      };
    }
  };
}

/**
 * 
 * @param {*} $document 
 * @returns 下拉框组件
 */
function elSelect($document) {
  return {
    restrict: 'E',
    templateUrl: './component/el-select/select.html', // 指令的HTML模板
    scope: {
      options: '=',
      selected: '=',
      placeholder: '@',
      multiple: '=',
      filterable: '@',
      onChange: '&',
      collapseTags: '@',
      disabled: '@',
      clearable: '@',
      remote: '@',
      remoteMethod: '&',
      loading: '@',
      class: '@',
      value: '@',
      label: '@',
      size: '@'
    },
    controller: function ($scope) {
      // 暴露change
      this.change = $scope.onChange
    },
    link: function (scope, element, attrs, ctrl) {
      // 初始化状态
      scope.isOpen = false;
      scope.flag = false;
      scope.readonly = false;
      scope.hoverIndex = -1;
      scope.optionItems = []
      if (!scope.selected) {
        scope.multiple ?
          scope.selected = [] :
          scope.selected = "";
      }

      // 清空输入框内容
      scope.clear = function () {
        scope.ngModel = ''
        scope.selected = ''
      }

      // 过滤条件
      scope.searchFilter = function (option) {
        if (scope.remote) {
          return
        }
        if (scope.multiple || !scope.filterable) {
          return option
        }
        return !scope.ngModel ||
          option?.label.toLowerCase().includes(scope.ngModel.toLowerCase());
      };

      // 判断是否选中
      scope.isSelected = function (value) {
        return scope.multiple ?
          scope.selected.includes(value) :
          scope.selected === value;
      };

      // 控制清空按钮显示
      scope.onMouseenter = function () {
        scope.flag = true
      }

      // 控制清空按钮关闭
      scope.onMouseleave = function () {
        scope.flag = false
      }

      // 显示文本处理
      function updateDisplayText() {
        if (scope.multiple) {
          const selectedLabels = scope.options
            .filter(function (opt) {
              return scope.selected.includes(opt.value)
            })
            .map(function (opt) {
              return opt.label
            });

          function getDisplayText(labels, collapse) {
            if (!labels.length) return '';

            return collapse ?
              labels.length > 1 ?
                `${labels[0]}, +${labels.length - 1}` :
                labels[0] :
              labels.join(', ');
          };

          scope.ngModel = getDisplayText(selectedLabels, scope.collapseTags);
        } else {
          const selectedOption = scope.options.find(function (opt) {
            return opt.value === scope.selected
          });
          scope.ngModel = selectedOption ? selectedOption.label : '';
        }
      }

      // 切换下拉状态
      scope.toggle = function () {
        scope.focus = true
        scope.isOpen = !scope.isOpen;
      };

      // 选择选项
      scope.selectOption = function (option) {
        if (option.disabled) return;

        if (scope.multiple) {
          const index = scope.selected.indexOf(option.value);
          if (index > -1) {
            scope.selected.splice(index, 1);
          } else {
            if (!Array.isArray(scope.selected)) {
              scope.selected = []
            }
            scope.selected.push(option.value);
          }
        } else {
          scope.selected = option.value;
          scope.isOpen = false;
        }

        updateDisplayText();
        // 调用ctrl中change
        ctrl.change({
          selected: scope.selected
        });
      };

      // 鼠标悬停
      scope.setHover = function (index) {
        scope.hoverIndex = index;
      };

      // 点击外部关闭
      const clickHandler = function (event) {
        if (!element[0].contains(event.target)) {
          scope.focus = false
          scope.$apply(function () { scope.isOpen = false });
        }
      };
      $document.on('click', clickHandler);
      // 销毁清理
      element.on('$destroy', function () {
        $document.off('click', clickHandler);
      });

      function isPlainObjectArray(arr) {
        return arr.every(function (element) {
          return element !== null &&
            Object.prototype.toString.call(element) === '[object Object]' // 仅限普通对象
        });
      }

      // 初始化显示文本
      updateDisplayText();

      // 监听数据变化
      scope.$watch('selected', updateDisplayText, true);

      scope.$watch('options', function (newValue, oldValue) {
        if (isPlainObjectArray(newValue)) {
          scope.optionItems = newValue.map(function (item) { return ({ label: item[scope.label], value: item[scope.value] }) })
        } else {
          scope.optionItems = newValue.map(function (item) {
            return ({
              label: item,
              value: item
            })
          })
        }
      })
      // 当输入框没值时，清空选择状态
      scope.$watch('ngModel', function (param) {
        if (!param) {
          scope.clear()
        }
      }, true);
      scope.$watch('filterable', function (param) {
        // 添加输入功能
        const nodes = element[0].children[0].children[0].children[0]
        // 单选才可以搜索
        if (!scope.multiple) {
          nodes.setAttribute("readonly", "readonly");
        }
        if (param) {
          nodes.removeAttribute("readonly");
        }
      }, true);
    }
  };
}

/**
 * 
 * @param {*} $document 
 * @returns 日期选择器组件
 */
function elDatePicker($document) {
  return {
    restrict: 'E',
    templateUrl: './component/el-date-picker/datePicker.html', // 指令的HTML模板
    scope: {
      date: '=',
      placeholder: '@',
      onChange: '&',
      size: '@'
    },
    link: function (scope, element) {
      // 初始化
      scope.isOpen = false;
      scope.isClose = false;
      scope.currentMonth = scope.date ? new Date(scope.date) : new Date();

      scope.clear = function () {
        scope.date = ''
      }

      // 生成日历
      const generateCalendar = function () {
        const year = scope.currentMonth.getFullYear();
        const month = scope.currentMonth.getMonth();
        const firstDay = new Date(year, month, 1);
        const lastDay = new Date(year, month + 1, 0);
        const panelDom = element[0].children[0].children[1];
        panelDom.style = `position: absolute;
        top: 40px;
        left: 0px;
        transform-origin: center bottom 0px;
        z-index: 2003;`
        const calendar = [];
        let week = [];

        // 补齐上月日期
        const prevMonthDays = firstDay.getDay(); // 0表示周日
        for (let i = prevMonthDays; i > 0; i--) {
          const date = new Date(year, month, 1 - i);
          week.push(createDayObject(date, false));
        }

        // 本月日期
        for (let d = 1; d <= lastDay.getDate(); d++) {
          const date = new Date(year, month, d);
          week.push(createDayObject(date, true));

          if (week.length === 7) {
            calendar.push(week);
            week = [];
          }
        }
        const nextMonthDays = 7 - week.length;
        if (nextMonthDays > 0) {
          for (let i = 1; i <= nextMonthDays; i++) {
            const date = new Date(year, month + 1, i);
            week.push(createDayObject(date, false));
          }
          calendar.push(week);
        }

        scope.calendar = calendar;
      };

      function createDayObject(date, isCurrentMonth) {
        const today = new Date();
        return {
          date: date,
          isCurrentMonth: isCurrentMonth,
          isToday: date.toDateString() === today.toDateString(),
          isSelected: scope.date && date.toDateString() === scope.date.toDateString()
        };
      };

      // 切换面板
      scope.toggle = function () {
        scope.isOpen = !scope.isOpen;
        generateCalendar();
      };

      // 切换年份
      scope.changeYear = function (offset) {
        scope.currentMonth.setYear(scope.currentMonth.getFullYear() + offset);
        scope.currentMonth = new Date(scope.currentMonth); // 触发更新
        generateCalendar();
      };

      // 切换月份
      scope.changeMonth = function (offset) {
        scope.currentMonth.setMonth(scope.currentMonth.getMonth() + offset);
        scope.currentMonth = new Date(scope.currentMonth); // 触发更新
        generateCalendar();
      };

      // 选择日期
      scope.selectDate = function (date) {
        scope.date = new Date(date);
        scope.onChange({
          date: scope.date
        });
        scope.isOpen = false;
        generateCalendar();
      };

      // 监听月份变化
      scope.$watch('currentMonth', generateCalendar);

      // 点击外部关闭
      const clickHandler = function (event) {
        if (!element[0].contains(event.target)) {
          scope.$apply(function () { scope.isOpen = false });
        }
      };

      $document.on('click', clickHandler);
      element.on('$destroy', function () { $document.off('click', clickHandler) });
    }
  };
}

/**
 * 
 * @param {*} $document 
 * @param {*} $timeout 
 * @param {*} $filter 
 * @returns 日期范围选择器
 */
function elDateRangePicker($document, $timeout, $filter) {
  return {
    restrict: 'E',
    require: 'ngModel',
    scope: {
      disabled: '=?',
      startPlaceholder: '@',
      endPlaceholder: '@',
      format: '@',
      size: '@'
    },
    templateUrl: './component/el-date-range-picker/dateRangePicker.html', // 指令的HTML模板
    link: function (scope, element, attrs, ngModel) {
      // 初始化数据
      scope.currentDate = new Date();
      scope.isVisible = false;
      scope.currentSelect = 'start'; // 当前选择的输入框
      scope.leftPanel = { date: new Date(), weeks: [], align: 'left' };
      scope.rightPanel = { date: new Date(), weeks: [], align: 'right' };
      scope.showClear = false;
      scope.tempStart = null;
      scope.tempEnd = null;

      // 生成月历
      function generateCalendar(date) {
        const year = date.getFullYear();
        const month = date.getMonth();
        const firstDay = new Date(year, month, 1);
        const calendar = [];
        let currentDate = new Date(firstDay);

        // 回退到最近周一的起始点
        currentDate.setDate(currentDate.getDate() - ((firstDay.getDay() + 6) % 7)); // 调整为周一开始

        // 始终生成6周
        for (let week = 0; week < 6; week++) {
          const weekDays = [];
          for (let day = 0; day < 7; day++) {
            const isCurrentMonth = currentDate.getMonth() === month;
            weekDays.push(createDayObject(new Date(currentDate), isCurrentMonth));
            currentDate.setDate(currentDate.getDate() + 1);
          }
          calendar.push(weekDays);
        }

        return calendar;
      };

      function createDayObject(date, isCurrentMonth) {
        return {
          date: date,
          isCurrentMonth: isCurrentMonth,
        };
      };

      // 更新面板
      const updatePanels = function () {
        scope.leftPanel.weeks = generateCalendar(scope.leftPanel.date);
        scope.rightPanel.date = new Date(scope.leftPanel.date);
        scope.rightPanel.date.setMonth(scope.leftPanel.date.getMonth() + 1);
        scope.rightPanel.weeks = generateCalendar(scope.rightPanel.date);
      };

      // 位置计算
      const calcPosition = function () {
        let rect = element[0].children[0].getBoundingClientRect();
        console.log(element[0].children[0]);
        scope.panelPosition = {
          top: rect.height + 5 + 'px',
          left: '0px'
        };
        console.log(scope.panelPosition);
      };

      scope.getDayClass = function (dates) {
        const currentDay = $filter('date')(dates.date, scope.format || 'yyyy-MM-dd');
        const currentTime = new Date(dates.date).getTime();

        // 原始日期判断（优先级最高）
        if (currentDay === $filter('date')(scope.currentDate, scope.format || 'yyyy-MM-dd')) return 'today';
        if (currentDay === scope.startText) return 'start-date';
        if (currentDay === scope.endText) return 'end-date';
        if (!dates.isCurrentMonth) return 'next-month prev-month';

        // 临时范围判断（仅在单边已选择时生效）
        if (scope.tempStart && scope.tempEnd) {
          const tempStartTime = new Date(scope.tempStart).getTime();
          const tempEndTime = new Date(scope.tempEnd).getTime();
          const isTempStart = currentDay === $filter('date')(scope.tempStart, scope.format);
          const isTempEnd = currentDay === $filter('date')(scope.tempEnd, scope.format);

          if (isTempStart) return 'start-date';
          if (isTempEnd) return 'end-date';
          if (currentTime > tempStartTime && currentTime < tempEndTime) return 'available in-range';
        }
      }

      scope.onMouseenter = function (date) {
        const hoverDate = new Date(date);
        const hasStart = !!scope.startText;
        const hasEnd = !!scope.endText;

        // 清除旧临时范围
        scope.tempStart = scope.tempEnd = null;

        // 只在单边已选择时生成临时范围
        if (hasStart !== hasEnd) { // XOR 判断
          const anchorDate = hasStart ? new Date(scope.startText) : new Date(scope.endText);
          scope.tempStart = hoverDate < anchorDate ? hoverDate : anchorDate;
          scope.tempEnd = hoverDate < anchorDate ? anchorDate : hoverDate;
        }
      }

      // 日期选择
      scope.selectDate = function (date) {
        if (scope.disabled) return;

        const currentValue = ngModel.$viewValue || {};

        if (scope.currentSelect === 'start') {
          currentValue.start = date;
          // 自动切换焦点到结束日期
          if (!currentValue.end || date > currentValue.end) {
            scope.currentSelect = 'end';
          }
        } else {
          currentValue.end = date;
          // 自动切换焦点到开始日期
          if (!currentValue.start || date < currentValue.start) {
            scope.currentSelect = 'start';
          }
        }

        // 自动交换错误顺序
        if (currentValue.start && currentValue.end && currentValue.start > currentValue.end) {
          [currentValue.start, currentValue.end] = [currentValue.end, currentValue.start];
        }

        ngModel.$setViewValue(currentValue);
        updateDisplay();
        if (currentValue.start && currentValue.end) scope.isVisible = false;
      };

      // 打开选择器
      scope.openPicker = function (type) {
        ngModel.$viewValue = {}
        if (scope.disabled) return;
        scope.currentSelect = type;
        scope.isVisible = true;
        initPanelDates();
        $timeout(function () {
          calcPosition();
          updatePanels();
        });
      };

      // 初始化面板日期
      const initPanelDates = function () {
        const currentValue = ngModel.$viewValue || {};
        const refDate = currentValue[scope.currentSelect] || new Date();
        scope.leftPanel.date = new Date(refDate);
        scope.rightPanel.date = new Date(refDate);
        scope.rightPanel.date.setMonth(scope.rightPanel.date.getMonth() + 1);
      };

      // 切换年份
      scope.changeYear = function (step) {
        scope.leftPanel.date.setYear(scope.leftPanel.date.getFullYear() + step);
        updatePanels();
      };
      // 月份切换
      scope.changeMonth = function (step) {
        scope.leftPanel.date.setMonth(scope.leftPanel.date.getMonth() + step);
        updatePanels();
      };

      // 更新显示值
      const updateDisplay = function () {
        const value = ngModel.$viewValue || {};
        console.log(value);
        scope.startText = value.start ?
          $filter('date')(value.start, scope.format || 'yyyy-MM-dd') : '';
        scope.endText = value.end ?
          $filter('date')(value.end, scope.format || 'yyyy-MM-dd') : '';
        scope.showClear = !!value.start || !!value.end;
      };

      // 清除选择
      scope.clear = function ($event) {
        $event.stopPropagation();
        ngModel.$setViewValue({});
        updateDisplay();
        scope.isVisible = false;
      };

      // 点击外部关闭
      $document.on('click', function (event) {
        if (!element[0].contains(event.target)) {
          scope.$apply(function () { scope.isVisible = false });
        }
      });

      // 数据监听
      ngModel.$render = function () { updateDisplay() };

      // 初始化
      updatePanels();
    }
  };
}

/**
 * 
 * @returns 主菜单容器
 */
function elMenu() {
  return {
    restrict: 'E',
    transclude: true,
    scope: {
      mode: '@', // horizontal/vertical
      defaultActive: '@', // 默认激活项
      activeIndex: '=', // 双向绑定激活项
      onSelect: '&', // 选择回调
      backgroundColor: '@',
      textColor: '@',
      activeTextColor: '@'
    },
    templateUrl: './component/navMenu/el-menu.html', // 指令的HTML模板
    controller: ['$scope', '$timeout', function ($scope, $timeout) {
      const submenus = {}; // 存储所有子菜单实例 [3](@ref)

      this.registerSubmenu = function (scope, level) {
        if (!submenus[level]) submenus[level] = [];
        submenus[level].push(scope);
      };

      this.closeOtherSubmenus = function (currentIndex, currentLevel) {
        const siblings = submenus[currentLevel] || [];
        siblings.forEach(submenu => {
          if (submenu.index !== currentIndex) {
            submenu.isOpen = false;
            $timeout(() => { }, 0); // 触发脏检查
          }
        });
        $scope.$broadcast('close-siblings', currentIndex); // 广播事件
      };

      // 管理子菜单状态
      this.isActive = function (index) {
        return $scope.activeIndex === index;
      };

      this.setActive = function (index) {
        $scope.onSelect({ selected: index })
        $scope.activeIndex = $scope.mode !== 'vertical' ? index.slice(0, 1) : index;
      };

      this.getScope = function () {
        return {
          mode: $scope.mode,
          backgroundColor: $scope.backgroundColor,
          textColor: $scope.textColor,
          activeTextColor: $scope.activeTextColor,
          activeIndex: $scope.activeIndex,
        }
      }
    }],
    link: function (scope) {
      if (scope.defaultActive) {
        scope.activeIndex = scope.defaultActive;
      }
    }
  };
}

/**
 * 
 * @returns 普通菜单项
 */
function elMenuItem($location, ColorService) {
  return {
    restrict: 'E',
    require: '^elMenu',
    transclude: true,
    scope: {
      index: '@',
      isOpen: '='
    },
    templateUrl: './component/navMenu/el-menu-item.html', // 指令的HTML模板
    link: function (scope, element, attrs, menuCtrl) {
      scope.isActive = menuCtrl.isActive(scope.index);
      scope.isSubActive = $location.$$url === attrs.to;
      scope.scopeData = menuCtrl.getScope()
      scope.handleClick = function () {
        menuCtrl.setActive(scope.index);
        $location.path(attrs.to);
      };

      scope.$watch(function () {
        scope.isSubActive = $location.$$url === attrs.to;
        return menuCtrl.isActive(scope.index);
      }, function (newVal) {
        scope.isActive = newVal;
      });

      scope.onMouseenter = function (event) {
        if (scope.scopeData.mode === 'vertical') {
          const className = event.target.className
          if (className.indexOf('el-submenu__title') !== -1 || className.indexOf('el-menu-item') !== -1)
          event.target.style.backgroundColor = ColorService.darken(scope.scopeData.backgroundColor, 30)
          return
        }
      }

      scope.onMouseleave = function (event) {
        if (scope.scopeData.mode === 'vertical') {
          const className = event.target.className
          if (className.indexOf('el-submenu__title') !== -1 || className.indexOf('el-menu-item') !== -1)
          event.target.style.backgroundColor = scope.scopeData.backgroundColor
          return
        }
      }

      if (attrs.to) {
        element.on('click', function () {
          scope.isSubActive = scope.index.length > 1 ? true : false
          $location.path(attrs.to);
          if (scope.scopeData.mode !== 'vertical')
            scope.$emit("isOpen", false)
        });
      }
    }
  };
}

/**
 * 
 * @returns 子菜单
 */
function elSubmenu($timeout, ColorService) {
  return {
    restrict: 'E',
    require: '^elMenu',
    transclude: {
      title: '?titleSlot' // '?' 表示该插槽是可选的
    },
    scope: {
      index: '@',
      title: '@',
      data: '@'
    },
    templateUrl: './component/navMenu/el-submenu.html', // 指令的HTML模板
    controller: function ($scope) {
      $scope.$on('isOpen', function (event, params) {
        $scope.isOpen = params
      })
    },
    link: function (scope, element, attrs, menuCtrl) {
      scope.isOpen = false;
      scope.scopeData = menuCtrl.getScope()
      scope.isActive = menuCtrl.isActive(scope.index.slice(0, 1));
      scope.level = scope.index.split('-').length
      const panelDom = element[0].children[0].children[1];
      const activeIndexs = scope.scopeData.activeIndex.split('-');
      const currentIndexs = scope.index.split('-');
      let shouldOpen = true;
      let hoverTimer;
      let hoverTimerOver;
      let hoverTimerbg;

      // 检查当前菜单是否在激活路径中
      for (let i = 0; i < currentIndexs.length; i++) {
        if (activeIndexs[i] !== currentIndexs[i]) {
          shouldOpen = false;
          break;
        }
      }

      if (shouldOpen) {
        scope.isOpen = false;
        setPanelStyle(); // 强制更新样式
      }

      function setPanelStyle() {
        const dom = element[0].querySelector('.el-submenu__title')
        const offsetLeft = element[0].querySelector('.el-submenu__title').offsetLeft
        const offsetWidth = element[0].querySelector('.el-submenu__title').offsetWidth
        scope.level = scope.index.split('-').length
        if (scope.scopeData.mode !== 'vertical') {
          panelDom.style = `position: absolute;
          top: ${dom.offsetHeight}px;
          left: ${scope.level > 1 ? offsetWidth : offsetLeft}px;
          transform-origin: center bottom 0px;
          z-index: 2003;`
        } else {
          const menu = element[0].querySelector('.el-menu')
          menu.className = 'el-menu collapse-trapow v-enter-active v-enter-to'
          if (!scope.isOpen) {
            menu.style = `height: ${menu.children[0].children.length * 50}px;overflow:hidden;background-color: ${menu.style.backgroundColor}`
          } else {
            menu.style = `height: 0px;overflow:hidden;padding-top: 0px;padding-bottom: 0px;background-color: ${menu.style.backgroundColor}`
          }
          hoverTimerbg = $timeout(() => {
            const titles = element[0].querySelectorAll('.el-submenu__title')
            const items = element[0].querySelectorAll('.el-menu-item')
            scope.isOpen = !scope.isOpen;
            menu.className = 'el-menu'
            menu.style = `background-color: ${menu.style.backgroundColor};`
            titles.forEach(function (d, i) {
              if (i !== 0)
                d.style = `padding-left: ${(scope.level + 1) * 20}px;color: ${d.style.color};background-color: ${scope.scopeData.backgroundColor};`
            })
            items.forEach(function (d) {
              d.style = `padding-left: ${(scope.level + 1) * 20}px;color: ${d.style.color};background-color: ${scope.scopeData.backgroundColor};`
            })
          })
        }
      }

      menuCtrl.registerSubmenu(scope, scope.level); // 新增：向父级注册实例

      scope.toggleMenu = function () {
        setPanelStyle()
        // 调用父控制器方法关闭其他子菜单 [2](@ref)
        menuCtrl.closeOtherSubmenus(scope.index, scope.level); // 新增：关闭其他菜单逻辑
        if (scope.scopeData.mode !== 'vertical') {
          menuCtrl.setActive(scope.index)
          scope.isActive = menuCtrl.isActive(scope.index);
        }
      };

      scope.onMouseenter = function (event) {
        if (scope.scopeData.mode === 'vertical') {
          const className = event.target.className
          if (className.indexOf('el-submenu__title') !== -1 || className.indexOf('el-menu-item') !== -1)
          event.target.style.backgroundColor = ColorService.darken(scope.scopeData.backgroundColor, 30)
          return
        }
        $timeout.cancel(hoverTimer)
        $timeout.cancel(hoverTimerbg)
        $timeout.cancel(hoverTimerOver)
        setPanelStyle()
        hoverTimer = $timeout(function () {
          scope.isOpen = true;
        }, 300)
      }

      scope.onMouseleave = function (event) {
        if (scope.scopeData.mode === 'vertical') {
          const className = event.target.className
          if (className.indexOf('el-submenu__title') !== -1 || className.indexOf('el-menu-item') !== -1)
          event.target.style.backgroundColor = scope.scopeData.backgroundColor
          return
        }
        $timeout.cancel(hoverTimer)
        $timeout.cancel(hoverTimerbg)
        $timeout.cancel(hoverTimerOver)
        hoverTimerOver = $timeout(function () {
          scope.isOpen = false;
        }, 300)
      }

      scope.$watch(function () {
        return menuCtrl.isActive(scope.index);
      }, function (newVal) {
        scope.isActive = newVal;
      });

      // 新增：监听父控制器的关闭事件
      scope.$on('close-submenus', function (event, currentIndex) {
        if (scope.index !== currentIndex) {
          scope.isOpen = false;
        }
      });

      // 点击外部关闭子菜单
      angular.element(document).on('click', function (event) {
        if (!element[0].contains(event.target) && scope.scopeData.mode !== 'vertical') {
          scope.$apply(function () {
            scope.isOpen = false;
          });
        }
      });
    }
  };
}

/**
 * 
 * @returns 菜单项分组
 */
function elMenuItemGroup() {
  return {
    restrict: 'E',
    transclude: true,
    templateUrl: './component/navMenu/el-menu-item-group.html', // 指令的HTML模板
    scope: {
      title: '@'
    }
  };
}

/**
 * 
 * @param {*} $compile 
 * @returns 多级菜单
 */
function menuItem($compile) {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      item: '='
    },
    templateUrl: './component/navMenu/menuItem.html', // 指令的HTML模板
    link: function (scope, element) {
      // 自动处理嵌套层级
      if (scope.item.children && scope.item.children.length) {
        $compile(element.contents())(scope);
      }
    }
  };
}

/**
 * 
 * @returns 表格
 */
function elTable($timeout) {
  return {
    restrict: 'E',
    transclude: true,
    scope: {
      data: '=', // 表格数据
      stripe: '@', // 斑马纹
      border: '@', // 边框
      height: '@', // 高度
      sortMethod: '&',
      clickMethod: '&'
    },
    templateUrl: './component/el-table/table.html',
    controller: function ($scope) {
      $scope.leftFixedColumns = [];
      $scope.rightFixedColumns = [];
      $scope.columns = [];
      $scope.leftWidth = 0;
      $scope.rightWidth = 0;
      // 注册列的方法
      this.addColumn = function (col) {
        if (col.fixed === 'left') {
          $scope.leftFixedColumns.push(col);
          $scope.leftWidth += parseInt(col.width) || 0;
        } else if (col.fixed === 'right') {
          $scope.rightFixedColumns.push(col);
          $scope.rightWidth += parseInt(col.width) || 0;
        }

        $scope.columns.push(col)
      };
      // 滚动同步逻辑
      this.syncScroll = function (scrollLeft) {
        $scope.$broadcast('syncScroll', scrollLeft);
      };

      // 暴露排序方法
      this.sortData = $scope.sortMethod()
      this.onClick = $scope.clickMethod()
      console.log($scope, 11);
    },
    link: function (scope, element, attrs, ctrl) {
      scope.sort = function (prop, order, event) {
        // scope.tableHeight= 0
        const target = event.currentTarget.closest('th');
        if (!target) return;

        const classList = target.classList;
        let newOrder = '';

        if (classList.contains('ascending')) {
          classList.replace('ascending', 'descending');
          newOrder = 'desc';
        } else if (classList.contains('descending')) {
          classList.remove('descending');
          newOrder = '';
        } else {
          classList.add('ascending');
          newOrder = 'asc';
        }
        // 触发数据排序
        ctrl.sortData(prop, newOrder);
      };
      scope.ngClick = ctrl.onClick

      // 监听主表格滚动事件
      const bodyWrapper = element[0].querySelector('.el-table__body-wrapper');
      const tableHeader = element[0].querySelector('.el-table__header-wrapper');
      bodyWrapper.addEventListener('scroll', function (e) {
        scope.$apply(function () {
          tableHeader.scrollLeft = e.target.scrollLeft
        });
      });
      // 初始化后计算高度
      $timeout(function () {
        const headerHeight = element[0].querySelector('.el-table__header').offsetHeight;
        const tableWidth = element[0].querySelector('.el-table').offsetWidth;
        const bodyHeight = bodyWrapper.offsetHeight;
        scope.tableHeight = headerHeight + bodyHeight;
        scope.headerHeight = headerHeight
        scope.tableWidth = tableWidth
      }, 60);
      $timeout(function () {
        const tableWidth = element[0].querySelector('.el-table').offsetWidth;
        const tableBodyWidth = element[0].querySelector('.el-table__body').scrollWidth;
        const tableHeigth = element[0].querySelector('.el-table').offsetHeight;
        const scrollHeight = element[0].querySelector('.el-table__body').scrollHeight;
        const classList = element[0].querySelector('.el-table').classList
        if (tableBodyWidth > tableWidth) {
          classList.add('el-table--scrollable-x')
        } else {
          classList.remove('el-table--scrollable-x');
        }
        if (scrollHeight > tableHeigth) {
          classList.add('el-table--scrollable-y')
        } else {
          classList.remove('el-table--scrollable-y');
        }
      }, 80);
    }
  };
}

/**
 * 
 * @returns 表格列
 */
function elTableColumn($sce, $compile) {
  return {
    restrict: 'E',
    require: '^elTable',
    transclude: true,
    scope: {
      prop: '@',
      label: '@',
      width: '@',
      fixed: '@',
      sortable: '@'
    },
    link: function (scope, element, attrs, ctrl, transclude) {
      transclude(function (clone, transcludeScope) {
        // 检查是否存在有效自定义内容
        let hasCustomTemplate = false;
        let templateHtml = '';

        // 过滤出有效的元素节点
        const validNodes = Array.from(clone).filter(function (node) { return node.nodeType === Node.ELEMENT_NODE });
        // 动态插入 row 参数到 ng-click
        validNodes.forEach(function (node) {
          const button = node.querySelectorAll('button')
          button.forEach(function (b) {
            if (b.nodeName === 'BUTTON' && b.hasAttribute('onClick')) {
              const originalNgClick = b.getAttribute('onClick');
              b.removeAttribute('onClick')
              b.setAttribute('ng-click', `${originalNgClick}`); // 添加 row 参数
            }
          })
        });
        if (validNodes.length > 0) {
          // 编译自定义内容
          // 编译并绑定到父控制器作用域
          const compiledClone = $compile(validNodes)(transcludeScope);
          templateHtml = compiledClone[0].outerHTML;
          hasCustomTemplate = true;
        }

        // 添加列配置
        ctrl.addColumn({
          prop: scope.prop,
          label: scope.label,
          width: scope.width,
          fixed: scope.fixed,
          sortable: scope.sortable === 'true',
          templateFlag: hasCustomTemplate, // 直接使用布尔值
          template: function (rowScope) {  // 接收行作用域参数
            const template = angular.element(templateHtml);
            const compiled = $compile(template)(rowScope);
            return compiled[0].outerHTML;
          }
        });
      });
    }
  };
}

/**
 * 
 * @returns 滚动同步指令
 */
function syncScroll() {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      scope.$on('syncScroll', function (event, scrollLeft) {
        element[0].scrollTop = scrollLeft;
      });
    }
  };
}

/**
 * 
 * @returns 输入框
 */
function elInput() {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      ngModel: '=',
      placeholder: '@',
      clearable: '@',
      prefixIcon: '@',
      suffixIcon: '@',
      disabled: '@',
      fixed: '@',
      size: '@',
      readonly: '@',
      commas: '@'
    },
    templateUrl: './component/el-input/input.html',
    link: function (scope) {
      // 清除功能 [3](@ref)
      scope.clear = function () {
        scope.ngModel = '';
      };

      scope.onBlur = function () {
        scope.ngModel = scope.ngModel.toString().replace(/[^0-9.-]/g, '')
          .replace(/(?!^-)-/g, '')
          .replace(/^\./, '0.')
          .replace(/(\..*)\./g, '$1');
        if (scope.fixed) {
          scope.ngModel = parseFloat(scope.ngModel || 0).toFixed(scope.fixed)
          console.log(scope.ngModel);
        }
        if (scope.commas) {
          scope.ngModel = addCommas(scope.ngModel || 0)
        }
      }
      // 添加千分位分隔符
      function addCommas(value) {
        console.log(value);
        const parts = value.toString().split('.');
        parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
        return parts.join('.');
      }

      // 禁用状态处理 [4](@ref)
      scope.$watch('disabled', function (newVal) {
        if (newVal === 'true') {
          scope.ngModel = '';
        }
      });
    }
  };
}

/**
 * 
 * @returns 复合型输入框
 */
function elInputGroup($compile, $timeout) {
  return {
    restrict: 'E',
    replace: true,
    transclude: {
      prepend: '?elInputPrepend',
      input: '?elInputContent',
      append: '?elInputAppend'
    },
    templateUrl: './component/el-input/input-group.html',
    link: function (scope, element, attrs, ctrls, transclude) {
      $timeout(function () {
        const hasPrepend = element.find('el-input-prepend').length !== 1;
        const hasAppend = element.find('el-input-append').length !== 1;
        if (hasPrepend) {
          element[0].querySelector('.el-input-group__prepend').style = "display: none;"
        }
        if (hasAppend) {
          element[0].querySelector('.el-input-group__append').style = "display: none;"
        }
      })
      transclude(function (clone, transcludeScope) {
        const prepend = angular.element(element[0].querySelector('.el-input-group__prepend')); // 改为指令内部查找
        const append = angular.element(element[0].querySelector('.el-input-group__append'));
        const content = angular.element(element[0].querySelector('.el-input-group__content'));

        // 批量编译+插入（减少 DOM 操作次数）
        const compiledNodes = Array.from(clone)
          .filter(function (node) {
            return node.nodeType === Node.ELEMENT_NODE
          })
          .map(function (node) {
            const compiled = $compile(node)(transcludeScope);
            return { node, compiled };
          });
        compiledNodes.forEach(function ({ node, compiled }) {
          switch (node.localName) {
            case 'el-input-prepend':
              prepend.append(compiled);
              break;
            case 'el-input-append':
              append.append(compiled);
              break;
            case 'el-input-content':
              content.append(compiled);
              break;
            default:  // 未匹配的节点处理
              element.append(compiled); // 或按业务需求处理
          }
        });
      })
    }
  };
}

function elInputNumber() {
  return {
    restrict: 'E',
    require: 'ngModel',
    scope: {
      ngModel: '=',
      min: '@',
      max: '@',
      step: '@',
      disabled: '@',
      size: '@'
    },
    templateUrl: './component/el-input-number/input-number.html',
    link: function (scope) {
      // 初始化默认值
      scope.ngModel = parseFloat(scope.ngModel) || parseFloat(scope.min) || 0;

      // 减少数值
      scope.decrease = function () {
        if (scope.disabled === 'true') return;
        const newVal = scope.ngModel - parseFloat(scope.step || 1);
        scope.ngModel = Math.max(newVal, parseFloat(scope.min || -Infinity));
        checkLimits();
      };

      // 增加数值
      scope.increase = function () {
        if (scope.disabled === 'true') return;
        const newVal = scope.ngModel + parseFloat(scope.step || 1);
        scope.ngModel = Math.min(newVal, parseFloat(scope.max || Infinity));
        checkLimits();
      };

      // 输入验证
      scope.validate = function () {
        let val = parseFloat(scope.ngModel);
        if (isNaN(val)) val = parseFloat(scope.min) || 0;
        val = Math.max(val, parseFloat(scope.min || -Infinity));
        val = Math.min(val, parseFloat(scope.max || Infinity));
        scope.ngModel = val;
        checkLimits();
      };

      // 检查极限值
      function checkLimits() {
        scope.isMin = scope.ngModel <= parseFloat(scope.min);
        scope.isMax = scope.ngModel >= parseFloat(scope.max);
      }

      // 初始化检查
      checkLimits();
    }
  };
}

/**
 * 
 * @returns 开关
 */
function elSwitch() {
  return {
    restrict: 'E',
    scope: {
      model: '=ngModel',      // 双向绑定[1,3](@ref)
      disabled: '@',          // 禁用状态[2,6](@ref)
      activeColor: '@',       // 激活颜色
      inactiveColor: '@',     // 关闭颜色
      activeText: '@',        // 激活文字
      inactiveText: '@',      // 关闭文字
      width: '@'              // 总宽度
    },
    templateUrl: './component/el-switch/switch.html',
    link: function (scope) {
      // 初始化宽度（参考网页5的动态尺寸）
      scope.switchWidth = parseInt(scope.width) || 40;

      // 切换逻辑（参考网页6的事件处理）
      scope.toggle = function () {
        if (scope.disabled) return;
        scope.model = !scope.model;
      };
    }
  };
}

/**
 * 
 * @param {*} $document 
 * @param {*} $timeout 
 * @returns 时间选择器
 */
function elTimePicker($document, $timeout) {
  return {
    restrict: 'E',
    templateUrl: './component/el-time-picker/timePicker.html',
    scope: {
      ngModel: '=',        // 双向绑定
      placeholder: '@',    // 占位符
      disabledHours: '&',  // 禁用小时函数[5](@ref)
      disabledMinutes: '&',// 禁用分钟函数[5](@ref)
      disabledSeconds: '&',// 禁用秒函数[5](@ref)
      format: '@',          // 格式（默认HH:mm）[8](@ref)
      size: '@'
    },
    link: function (scope, element) {
      // 初始化配置
      scope.format = scope.format || 'HH:mm:ss';
      // 使用常量定义时间范围
      const HOURS_IN_DAY = 24;
      const MINUTES_IN_HOUR = 60;
      const SECONDS_IN_MINUTE = 60;

      // 通用函数创建时间范围数组
      const createTimeRange = function (length) { return Array.from({ length }, function (_, i) { return i }) };

      // 初始化时间范围
      scope.hours = createTimeRange(HOURS_IN_DAY);
      scope.minutes = createTimeRange(MINUTES_IN_HOUR);
      scope.seconds = createTimeRange(SECONDS_IN_MINUTE);

      scope.showPanel = false;

      // 使用单次 Date 对象创建减少重复调用
      const initDate = new Date();
      const [initialHours, initialMinutes, initialSeconds] = [
        initDate.getHours(),
        initDate.getMinutes(),
        initDate.getSeconds()
      ];

      // 合并时间对象初始化
      scope.oldTime = {
        hours: initialHours,
        minutes: initialMinutes,
        seconds: initialSeconds
      };

      // 使用对象解构简化赋值
      getTimes();

      // 面板切换方法优化
      scope.togglePanel = function () {
        if (scope.disabled) return;

        scope.showPanel = !scope.showPanel;

        if (scope.showPanel) {
          $timeout(function () {
            // 使用更可靠的 DOM 选择方式
            getScrollToCenter();
          }, 0, false); // 明确指定 invokeApply 为 false 提升性能
        }
      };

      // 通过鼠标移动事件固定时间标签位置
      scope.onMouseenter = function (event) {
        const scrollbarWrap = event.currentTarget;
        const clientHeight = scrollbarWrap.querySelector('li').clientHeight
        const currentAmount = Math.floor(scrollbarWrap.scrollTop / clientHeight)
        getItemCenter(scrollbarWrap, currentAmount)
      }

      // 固定时间在中间
      getItemCenter = function (event, amount) {
        const clientHeight = event.querySelector('li').clientHeight
        event.scrollTop = amount * clientHeight
      }

      function getTimes() {
        ({
          hours: scope.selectedHour,
          minutes: scope.selectedMinute,
          seconds: scope.selectedSecond
        } = scope.oldTime);
      }

      function getScrollToCenter() {
        // 使用更可靠的 DOM 选择方式
        const scrollContainers = Array.from(
          element[0].querySelectorAll('.el-scrollbar__wrap')
        );
        // 使用循环处理相似操作
        const timeComponents = ['hours', 'minutes', 'seconds'];
        scrollContainers.forEach(function (container, index) {
          const component = timeComponents[index];
          getItemCenter(container, scope.oldTime[component]);
        });
      }
      // 重置时间
      scope.cancel = function () {
        getScrollToCenter();
        getTimes();
        updateModel();
      }

      // 确定时间
      scope.confirm = function () {
        scope.oldTime.hours = scope.selectedHour;
        scope.oldTime.minutes = scope.selectedMinute;
        scope.oldTime.seconds = scope.selectedSecond;
        scope.showPanel = false;
        updateModel();
      }


      // 时间选择逻辑[8](@ref)
      scope.selectHour = function (event, h) {
        if (isDisabledHour(h)) return;
        getItemCenter(event.target.closest('div'), h)
        scope.selectedHour = h;
        updateModel();
      };

      scope.selectMinute = function (event, m) {
        if (isDisabledMinute(m)) return;
        getItemCenter(event.target.closest('div'), m)
        scope.selectedMinute = m;
        updateModel();
      };

      scope.selectSecond = function (event, s) {
        if (isDisabledSecond(s)) return;
        getItemCenter(event.target.closest('div'), s)
        scope.selectedSecond = s;
        updateModel();
      };

      // 禁用检查
      function isDisabledHour(h) {
        return scope.disabledHours() ? scope?.disabledHours()(h) : false;
      }

      function isDisabledMinute(m) {
        return scope.disabledMinutes() ? scope?.disabledMinutes()(m) : false;
      }

      function isDisabledSecond(s) {
        return scope.disabledSeconds() ? scope?.disabledSeconds()(s) : false;
      }

      // 模型更新
      function updateModel() {
        const timeStr = `${scope.selectedHour || '00'}:${scope.selectedMinute || '00'}:${scope.selectedSecond || '00'}`;
        scope.ngModel = moment(timeStr, 'HH:mm:ss').format(scope.format);
      }

      // 初始化选中时间
      scope.$watch('ngModel', function (newVal) {
        if (newVal) {
          const [h, m] = newVal.split(':');
          scope.selectedHour = parseInt(h);
          scope.selectedMinute = parseInt(m);
        }
      });

      // 销毁时移除监听
      scope.$on('$destroy', function () {
        $document.off('click', onClickBody);
      });

      // 点击外部关闭面板
      const onClickBody = function (event) {
        if (!element[0].contains(event.target)) {
          scope.$apply(function () { scope.showPanel = false });
        }
      };
      $document.on('click', onClickBody);
    }
  };
}

/**
 * 
 * @param {*} $http 
 * @param {*} $parse 
 * @param {*} $timeout 
 * @returns 上传
 */
function elUpload($http, $parse, $timeout) {
  return {
    restrict: 'E',
    transclude: true,
    templateUrl: './component/el-upload/upload.html',
    scope: {
      action: '@',         // 上传地址
      headers: '=',        // 请求头
      data: '=',           // 附加数据
      multiple: '@',       // 是否多选
      accept: '@',         // 文件类型
      drag: '@',           // 是否启用拖拽
      showFileList: '=',   // 显示文件列表
      onSuccess: '&',      // 成功回调
      onError: '&',        // 错误回调
      onRemove: '&',       // 删除回调
      onChange: '&',       // 上传回调
      beforeUpload: '&',    // 上传前钩子
      class: '@', // 自定义类名
      autoUpload: '=', // 自动上传
    },
    controller: ['$scope', '$element', function ($scope, $element) {
      // 初始化状态
      $scope.fileList = [];
      $scope.dragActive = false;
      $scope.isSelecting = false;
      const input = $element[0].querySelector('#fileInput');

      // 新增文件选择触发器
      $scope.triggerFileSelect = function () {
        if ($scope.isSelecting) return;
        if (!input) return;

        // 同步触发文件选择
        $scope.isSelecting = true;
        $timeout(function () {
          input.click();
          $scope.isSelecting = false;
        })
      };

      // 初始化文件监听
      const initFileInputListener = function () {
        angular.element(input).on('change', function (e) {
          $timeout(function () {
            const files = e.target.files;
            handleFileSelect(files);
          })
        });
      };

      // 修改后的文件处理方法
      const handleFileSelect = function (files) {
        if (!files || files.length === 0) return;

        Array.from(files).forEach(function (file) {
          const fileObj = {
            uid: Date.now(),
            name: file.name,
            size: file.size,
            raw: file,
            status: 'ready',
            percentage: 0
          };
          $scope.fileList.push(fileObj);
        });
        // 上传触发change回调
        $timeout(function () {
          $scope.onChange({ files: angular.copy($scope.fileList) })
        })
        // 自动开始上传
        if ($scope.autoUpload) {
          $scope.fileList.forEach(function (file) { this.upload(file) });
        }
      };

      // 初始化
      initFileInputListener();

      // 执行上传
      this.upload = function (file) {
        if ($scope.beforeUpload({ file })) return;

        const formData = new FormData();
        formData.append('file', file.raw);
        angular.forEach($scope.data, function (value, key) {
          formData.append(key, value);
        });

        file.status = 'uploading';
        $http({
          method: 'POST',
          url: $scope.action,
          data: formData,
          headers: $scope.headers,
          uploadEventHandlers: {
            progress: function (e) {
              file.percentage = Math.round(e.loaded / e.total * 100);
              $scope.$digest();
            }
          }
        }).then(function (res) {
          file.status = 'success';
          $scope.onSuccess({ res, file });
        }).catch(function (err) {
          file.status = 'error';
          $scope.onError({ err, file });
        });
      };

      // 删除文件
      $scope.handleRemove = function (file, index) {
        $scope.fileList.splice(index, 1);
        $scope.onRemove({ file });
      };

      // 预览文件
      $scope.handlePreview = function (file) {
        if (file.raw.type.startsWith('image/')) {
          const reader = new FileReader();
          reader.onload = function (e) { window.open(e.target.result) };
          reader.readAsDataURL(file.raw);
        }
      };
    }]
  };
}

/**
 * 
 * @returns 拖拽
 */
function elDropzone() {
  return {
    link: function (scope, elem, attrs) {
      elem.on('dragover', function (e) {
        e.preventDefault();
        scope.$apply(function () { scope.dragActive = true });
      });

      elem.on('dragleave', function () {
        scope.$apply(function () { scope.dragActive = false });
      });

      elem.on('drop', function (e) {
        e.preventDefault();
        scope.$apply(function () {
          scope.dragActive = false;
          const files = e.dataTransfer.files;
          scope.$eval(attrs.onDrop, { files });
        });
      });
    }
  };
}

/**
 * 
 * @returns 按钮
 */
function elButton() {
  return {
    restrict: 'E',
    transclude: true,
    replace: true,
    scope: {
      type: '@',
      size: '@',
      plain: '@',
      round: '@',
      circle: '@',
      ngDisabled: '@',
      loading: '@'
    },
    template: `
      <button class="el-button"
        ng-class="[
          'el-button--' + (type || 'default'),
          size ? 'el-button--' + size : '',
          {
            'is-plain': plain,
            'is-round': round,
            'is-circle': circle,
            'is-disabled': ngDisabled,
            'is-loading': loading === 'true'
          }
        ]">
        <span ng-transclude ng-if="loading === undefined || loading === 'false'"></span>
        <i ng-if="loading === 'true'" class="el-icon-loading"></i>
        <span ng-if="loading === 'true'">加载中</span>{{loading}}
      </button>
    `,
    link: function (scope, element, attrs) {
      // 处理点击事件
      element.on('click', function (event) {
        if (scope.ngDisabled) {
          event.preventDefault();
          event.stopImmediatePropagation();
        }
      });
    }
  };
}

/**
 * 
 * @returns 穿梭框
 */
function elTransfer() {
  return {
    restrict: 'E',
    templateUrl: './component/el-transfer/transfer.html',
    scope: {
      data: '=',           // 数据源格式：[{key, label, disabled}]
      value: '=',          // 已选中的key数组
      titles: '=?',         // 面板标题，默认 ['列表 1', '列表 2']
      filterable: '@',      // 是否显示搜索框
      filterMethod: '&',    // 自定义过滤方法
      onChange: '&'        // 变更回调
    },
    controller: ['$scope', function ($scope) {
      // 初始化配置
      $scope.titles = $scope.titles || ['列表 1', '列表 2'];
      $scope.searchQuery = { left: '', right: '' };
      $scope.disabled = true

      // 数据分区
      $scope.leftData = [];
      $scope.rightData = [];
      $scope.allChecked = {
        left: false,
        right: false
      }

      // 观察数据变化
      $scope.$watchCollection('data', updatePartition);
      // $scope.$watch('value', updatePartition);

      // 数据分区方法
      function updatePartition() {
        console.log(11);
        $scope.leftData = $scope.data.map(function (item) {
          return {
            ...item,
            checked: false
          }
        });

        $scope.rightData = $scope.value.map(function (key) {
          const found = $scope.data.find(function (d) { return d.key === key });
          return found ? { ...found, checked: false } : null;
        }).filter(Boolean);
      }

      // 计算选中数量
      $scope.checkedCount = {
        left: 0,
        right: 0
      };

      // 全选/取消全选
      $scope.toggleAll = function (side) {
        const data = side === 'left' ? $scope.leftData : $scope.rightData;
        const newState = $scope.allChecked[side];
        data.forEach(function (item) {
          if (!item.disabled) item.checked = newState;
        });
        this.computedChecked(side)
      };

      // 执行转移
      $scope.transferItems = function (direction) {
        const from = direction === 'left' ? 'right' : 'left';
        const to = direction === 'left' ? 'left' : 'right';

        const movedItems = $scope[from + 'Data']
          .filter(function (item) { return item.checked })
          .map(function (item) { return item.key });

        // 更新value数组
        $scope.value = direction === 'right'
          ? [...$scope.value, ...movedItems]
          : $scope.value.filter(function (k) { return !movedItems.includes(k) });

        // 触发回调
        $scope.onChange({
          value: $scope.value,
          moved: movedItems,
          direction: direction
        });
        // 重置选中状态
        $scope[to + 'Data'] = [...$scope[to + 'Data'], ...$scope[from + 'Data'].filter(function (item) { return item.checked })];
        $scope[from + 'Data'] = $scope[from + 'Data'].filter(function (item) { return !item.checked });
        $scope[from + 'Data'].forEach(function (d) { d.checked = false });
        $scope[to + 'Data'].forEach(function (d) { d.checked = false });
        $scope.checkedCount[from] = 0
        $scope.allChecked[from] = false
      };

      // 计算选中项
      $scope.computedChecked = function (side) {
        const data = side === 'left' ? $scope.leftData : $scope.rightData;
        $scope.checkedCount[side] = data.filter(function (item) { return item.checked && !item.disabled }).length;
      }
    }]
  };
}

/**
 * 
 * @param {*} $timeout 
 * @returns 分页
 */
function elPagination($timeout) {
  return {
    restrict: 'E',
    templateUrl: './component/el-pagination/pagination.html',
    scope: {
      total: '=',
      currentPage: '=',
      pageSize: '=',
      pageSizes: '=',
      onSizeChange: '&',
      onCurrentChange: '&',
      layout: '@',
      background: '@',
      jumpPage: '='
    },
    link: function (scope, element) {
      // 计算总页数
      scope.pageCount = Math.ceil(scope.total / scope.pageSize) || 1;
      // 初始化（双重保障）
      scope.jumpPage = scope.jumpPage || '';

      scope.pageSizeList = []

      // 手动监听输入事件
      element.find('.el-pagination__jump-input').on('input', function () {
        $timeout(function () {
          scope.jumpPage = this.value.replace(/[^0-9]/g, '');
        })
      });


      // 生成页码数组
      function generatePages() {
        const current = scope.currentPage;
        const pageCount = scope.pageCount;
        const pages = [];

        // 核心修复逻辑：避免重复值
        if (pageCount <= 7) {
          for (let i = 1; i <= pageCount; i++) {
            pages.push(i);
          }
        } else {
          pages.push(1);

          // 处理左侧省略号
          if (current > 4) {
            pages.push('...');
          }

          // 动态计算中间页码
          let start = Math.max(2, current - 1);
          let end = Math.min(pageCount - 1, current + 1);

          // 边界补偿逻辑
          if (current <= 4) {
            end = 5;
          } else if (current >= pageCount - 3) {
            start = pageCount - 4;
          }

          // 填充中间页码
          for (let i = start; i <= end; i++) {
            if (i > 1 && i < pageCount) {
              pages.push(i);
            }
          }

          // 处理右侧省略号
          if (current < pageCount - 3) {
            pages.push('...');
          }

          pages.push(pageCount);
        }

        // 二次去重保障
        return [...new Set(pages)];
      }

      // 页码点击
      scope.changePage = function (page) {
        if (page < 1 || page > scope.pageCount || page === scope.currentPage) return;
        scope.currentPage = page;
        scope.onCurrentChange({ page: page });
        updatePages();
      };

      // 跳转页面
      scope.jumpToPage = function () {
        const page = parseInt(scope.jumpPage);
        if (page >= 1 && page <= scope.pageCount) {
          scope.changePage(page);
        }
      };

      // 修改每页数量
      scope.handleSizeChange = function (selected) {
        scope.pageSize = selected
        scope.pageCount = Math.ceil(scope.total / scope.pageSize) || 1;
        if (scope.currentPage > scope.pageCount) {
          scope.currentPage = scope.pageCount;
        }
        scope.onSizeChange({ size: scope.pageSize });
        updatePages();
      };

      // 更新页码显示
      function updatePages() {
        scope.pages = generatePages();
      }

      // 初始化
      updatePages();
      scope.$watch('total', updatePages);
      scope.$watch('pageSizes', function (newValue) {
        scope.pageSizeList = newValue.map(function (d) { return { label: d + '条/页', value: d } })
      })
    }
  };
}

/**
 * 
 * @param {*} $document 
 * @returns 弹出框
 */
function elDialog($document, $compile) {
  return {
    restrict: 'E',
    templateUrl: './component/el-dialog/dialog.html',
    transclude: {
      'footer': '?footer',
      'content': 'content',
    },
    scope: {
      visible: '=',         // 是否显示
      title: '@',          // 标题
      width: '@',          // 宽度
      customClass: '@',    // 自定义类名
      showClose: '=',      // 显示关闭按钮
      showHeader: '@',     // 显示头部
      center: '=',         // 居中布局
      closeOnClickModal: '=', // 点击遮罩关闭
      fullscreen: '='      // 全屏模式
    },
    controller: ['$scope', function ($scope) {
      // 默认参数
      $scope.showClose = angular.isDefined($scope.showClose) ? $scope.showClose : true;
      $scope.showHeader = angular.isDefined($scope.showHeader) ? $scope.showHeader : true;
      $scope.closeOnClickModal = angular.isDefined($scope.closeOnClickModal) ? $scope.closeOnClickModal : true;

      // 添加 mask遮罩层 的方法
      addMaskDiv = function () {
        // 创建包含 Angular 绑定的模板
        const template = `
        <div class="v-modal" style="z-index: 2000;"></div>
      `;

        // 编译模板并链接作用域
        const compiled = $compile(template)($scope);

        compiled.on('click', function () {
          console.log(222);
        })

        // 添加到容器
        angular.element($document[0].body).append(compiled);

      };

      // 移除元素的控制器方法
      removeMask = function () {
        angular.element($document[0].body.querySelector('.v-modal')).remove();
      };

      // 关闭对话框
      $scope.handleClose = function (type) {
        removeMask()
        $scope.visible = false;
      };

      // 点击遮罩层
      $scope.handleWrapperClick = function () {
        if ($scope.closeOnClickModal) {
          $scope.handleClose();
        }
      };

      $scope.$watch('visible', function (newVal) {
        if (newVal) {
          addMaskDiv()
        } else {
          removeMask()
        }
      });

      // ESC 键关闭
      $document.on('keydown', function (e) {
        if (e.keyCode === 27 && $scope.visible) {
          $scope.$apply(function () { $scope.handleClose() });
        }
      });
    }],
    link: function (scope, element, attrs, ctrl, transclude) {
      transclude(function (clone, transcludeScope) {
        const targetBody = angular.element(element[0].querySelector('.el-dialog__body')); // 改为指令内部查找
        const targetFooter = angular.element(element[0].querySelector('.el-dialog__footer'));

        // 批量编译+插入（减少 DOM 操作次数）
        const compiledNodes = Array.from(clone)
          .filter(function (node) {
            return node.nodeType === Node.ELEMENT_NODE
          })
          .map(function (node) {
            const compiled = $compile(node)(transcludeScope);
            return { node, compiled };
          });

        compiledNodes.forEach(function ({ node, compiled }) {
          switch (node.localName) {
            case 'content':
              targetBody.append(compiled);
              break;
            case 'footer':
              targetFooter.append(compiled);
              break;
            default:  // 未匹配的节点处理
              element.append(compiled); // 或按业务需求处理
          }
        });
      })
      // 销毁时移除事件监听
      scope.$on('$destroy', function () {
        $document.off('keydown');
      });
    }
  };
}

/**
 * 
 * @returns 描述列表
 */
function elDescriptions($timeout) {
  return {
    restrict: 'E',
    transclude: true,
    scope: {
      title: '@',
      border: '@',
      column: '@',
      labelAlign: '@'
    },
    templateUrl: './component/el-descriptions/descriptions.html',
    controller: function ($scope) {
      const ctrl = this;
      ctrl.items = [];

      // 注册子项方法
      ctrl.registerItem = function (item) {
        ctrl.items.push(item);
        scheduleUpdate();
      };

      // 注销子项方法  
      ctrl.unregisterItem = function (item) {
        const index = ctrl.items.indexOf(item);
        if (index > -1) {
          ctrl.items.splice(index, 1);
          scheduleUpdate();
        }
      };

      // 防抖更新
      let updateTimer;
      function scheduleUpdate() {
        $timeout.cancel(updateTimer);
        updateTimer = $timeout(updateLayout, 50);
      }

      // 布局计算
      function updateLayout() {
        const columns = parseInt($scope.column) || 3;
        $scope.rows = [];

        for (let i = 0; i < ctrl.items.length; i += columns) {
          $scope.rows.push(ctrl.items.slice(i, i + columns));
        }
        console.log('Layout updated:', $scope.rows);
      }

      // 初始化更新
      scheduleUpdate();
    },
  };
}

function elDescriptionsItem() {
  return {
    restrict: 'E',
    require: '^elDescriptions',  // 关键：声明父依赖
    transclude: true,
    scope: {
      label: '@'
    },
    link: function (scope, element, attrs, parentCtrl) {
      console.log('子组件 link 触发');  // 调试日志

      // 生成唯一插槽标识
      scope.slot = `slot-${Math.random().toString(36).substr(2, 5)}`;

      // 注册到父组件
      const itemData = {
        label: scope.label,
        slot: scope.slot
      };
      parentCtrl.registerItem(itemData);

      // 销毁时清理
      element.on('$destroy', function () {
        parentCtrl.unregisterItem(itemData);
      });
    }
  };
}

/**
 * 
 * @returns 标签
 */
function elTag() {
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    scope: {
      type: '@',        // 类型：success/info/warning/danger
      closable: '@',    // 是否可关闭
      size: '@',        // 尺寸：medium/small/mini
      color: '@',       // 自定义颜色（优先级高于 type）
      border: '@',      // 是否有边框
      round: '@'        // 是否圆角
    },
    template: `
      <span class="el-tag el-tag--light"
           ng-class="[typeClass, sizeClass, borderClass, roundClass]"
           ng-style="customStyle" ng-transclude>
        <i class="el-tag__close el-icon-close" ng-if="closable" ng-click="handleClose()"></i>
      </span>
    `,
    link: function (scope, element, attrs) {
      // 动态类名
      scope.typeClass = scope.type ? `el-tag--${scope.type}` : '';
      scope.sizeClass = scope.size ? `el-tag--${scope.size}` : '';
      scope.borderClass = scope.border === 'true' ? 'is-border' : '';
      scope.roundClass = scope.round === 'true' ? 'is-round' : '';

      // 自定义颜色（优先级最高）
      scope.customStyle = {};
      if (scope.color) {
        scope.customStyle.backgroundColor = scope.color;
        scope.customStyle.borderColor = scope.color;
      }

      // 关闭事件
      scope.handleClose = function () {
        element.remove(); // 移除标签
        if (attrs.onClose) {
          scope.$eval(attrs.onClose); // 触发回调
        }
      };
    }
  };
}

/**
 * 
 * @param {*} $timeout 
 * @returns 标签页
 */
function elTabs($timeout) {
  return {
    restrict: 'E',
    transclude: true,
    templateUrl: './component/el-tabs/tabs.html',
    scope: {
      value: '=',
      type: '@'
    },
    controller: ['$scope', '$element', function ($scope, $element) {
      $scope.tabs = [];
      $scope.activeTab = null;
      $timeout(function () {
        const activeElement = $element[0].querySelector('.el-tabs__item');
        // 卡片样式取消激活栏
        if (!$scope.type) {
          $scope.activeBarStyle = {
            width: getContentWidth(activeElement) + 'px',
            transform: `translateX(20px)`
          };
        }
      })

      // 提取宽度计算逻辑到独立函数
      function getContentWidth(element) {
        const computedStyle = window.getComputedStyle(element);
        const boxSizing = computedStyle.boxSizing;
        const width = parseFloat(computedStyle.width);
        if (boxSizing === 'border-box') {
          const [paddingLeft, paddingRight, borderLeft, borderRight] =
            ['paddingLeft', 'paddingRight', 'borderLeftWidth', 'borderRightWidth']
              .map(function (prop) { return parseFloat(computedStyle[prop]) });
          return width - paddingLeft - paddingRight - borderLeft - borderRight;
        }
        return width; // content-box 模式直接返回
      }

      // 注册标签页
      this.addTab = function (tab) {
        $scope.tabs.push(tab);
        if (tab.active) {
          $scope.selectTab('', tab); // 默认激活第一个
        }
      };

      // 切换标签页
      $scope.selectTab = function (event, tab) {
        if (tab.disabled) return;
        $scope.value = tab.name
        $scope.tabs.forEach(function (t) { t.active = false });
        tab.active = true;
        $scope.activeTab = tab;
        $timeout(function () {
          const activeElement = $element[0].querySelectorAll('.el-tabs__item');
          const index = $scope.tabs.findIndex(function (d) { return d.active })
          updateActiveBar(event ? event.target : activeElement[index]);
        })
      };

      // 移除标签页
      $scope.removeTab = function (tab, event) {
        event.stopPropagation();
        const index = $scope.tabs.indexOf(tab);
        $scope.tabs.splice(index, 1);
        if (tab.active && $scope.tabs.length > 0) {
          $scope.selectTab(event.target, $scope.tabs[Math.max(0, index - 1)]);
        }
      };

      // 监听value触发更新
      this.watchParentValue = function (callback) {
        $scope.$watch('value', function (newVal) { callback(newVal) });
      };

      // 更新激活栏位置
      function updateActiveBar(event) {
        if (!$scope.activeTab) return;
        // 卡片样式取消激活栏
        if (!$scope.type) {
          $scope.activeBarStyle = {
            width: getContentWidth(event) + 'px',
            transform: `translateX(${event.offsetLeft + 20}px)`
          };
        }
      }
    }]
  };
}

function elTabPane() {
  return {
    restrict: 'E',
    require: '^elTabs',
    transclude: true,
    scope: {
      label: '@',
      name: '@',
      disabled: '@',
      closable: '@'
    },
    template: `
      <div class="el-tab-pane" ng-show="active">
        <ng-transclude></ng-transclude>
      </div>
    `,
    link: function (scope, element, attrs, tabsCtrl) {
      const value = scope.$parent.$parent.value
      // 触发子指令更新
      tabsCtrl.watchParentValue(function (newVal) {
        scope.active = attrs.name === newVal;
      });
      scope.active = attrs.name === value;
      tabsCtrl.addTab({
        label: scope.label,
        name: attrs.name,
        active: attrs.name === value || false,
        disabled: scope.$eval(attrs.disabled) || false,
        closable: scope.$eval(attrs.closable) || false
      });
    }
  };
}

/**
 * 
 * @returns Collapse 折叠面板
 */
function elCollapse() {
  return {
    restrict: 'E',
    transclude: true,
    scope: {
      items: '=',
      activeNames: '='
    },
    controller: function ($scope) {
      $scope.activeNames = $scope.activeNames || [];

      this.toggleItem = function (name) {
        const index = $scope.activeNames.indexOf(name);
        if (index === -1) {
          $scope.activeNames.push(name);
        } else {
          $scope.activeNames.splice(index, 1);
        }
      };

      this.isActive = function (name) {
        return $scope.activeNames.indexOf(name) > -1;
      };
    },
    template: `<div class="el-collapse" ng-transclude></div>`
  };
}

function elCollapseItem($timeout) {
  return {
    restrict: 'E',
    require: '^elCollapse',
    transclude: true,
    scope: {
      name: '@',
      title: '@'
    },
    link: function (scope, element, attrs, collapseCtrl) {
      const contentWrap = angular.element(element[0].querySelector('.el-collapse-item__wrap'));
      let contentHeight = 0;

      // 初始化高度
      $timeout(function () {
        contentHeight = contentWrap[0].scrollHeight;
      }, 50); // 确保DOM渲染完成

      // 动画控制函数
      const animateToggle = function (isOpening) {
        contentWrap[0].className = 'el-collapse-item__wrap v-leave-active collapse-transition v-leave-to'
        contentWrap[0].style = `height: ${isOpening ? contentHeight : 0}px;overflow: hidden;`
        // $timeout(function () {
        if (isOpening) {
          contentWrap[0].className = 'el-collapse-item__wrap'
          contentWrap[0].style = ''
        } else {
          contentWrap[0].style = 'display: none;'
        }
        // }, 100);
      };

      // 状态同步
      scope.isActive = collapseCtrl.isActive(scope.name);
      scope.$watch(
        function () { return scope.isActive; }, // 监视函数
        function (newVal, oldVal) {            // 回调函数
          animateToggle(newVal);
        }
      );

      // 点击事件
      scope.toggle = function () {
        collapseCtrl.toggleItem(scope.name);
        scope.isActive = collapseCtrl.isActive(scope.name);
        const willActive = !scope.isActive;
        animateToggle(willActive);
      };

      // 动画结束处理
      contentWrap.on('transitionend', function () {
        if (scope.isActive) {
          contentWrap.css('height', 'auto');
        }
      });
    },
    template: `
      <div class="el-collapse-item" ng-class="{ 'is-active': isActive }">
        <div class="el-collapse-item__header" ng-class="{ 'is-active': isActive }" ng-click="toggle()">
          {{ title }}
          <i class="el-icon-arrow-right el-collapse-item__arrow" 
          ng-class="{ 'is-active': isActive }"></i>
        </div>
        <div class="el-collapse-item__wrap">
          <div class="el-collapse-item__content">
            <ng-transclude></ng-transclude>
          </div>
        </div>
      </div>
    `,
    replace: true
  };
}

/**
 * 
 * @returns Link 文字链接
 */
function elLink() {
  return {
    restrict: 'E',
    transclude: true,
    replace: true,
    scope: {
      type: '@',
      href: '@',
      target: '@',
      disabled: '@',
      underline: '@'
    },
    template: `
      <a href="{{is-disabled ? 'javascript:void(0)' : href}}" target="target" class="el-link el-link--default" ng-class="[
        'el-link--' + (type || 'default'),
        underline ? 'is-underline' : '',
        disabled ? 'is-disabled' : '',
      ]">
        <span class="el-link--inner" ng-transclude></span>
      </a>
    `
  };
}

/**
 * 
 * @returns Layout 布局
 */
function elRow() {
  return {
    restrict: 'E',
    transclude: true,
    scope: { gutter: '@', type: '@', justify: '@' },
    template: `<div class="el-row" ng-class="[type ? 'el-row--' + type : '', justify ? 'is-justify-' + justify : '']" ng-transclude></div>`,
    link: function (scope, element) {
      if (scope.gutter) {
        element.children().css({
          'padding-left': scope.gutter / 2 + 'px',
          'padding-right': scope.gutter / 2 + 'px'
        });
        element.css('margin-left', -scope.gutter / 2 + 'px');
        element.css('margin-right', -scope.gutter / 2 + 'px');
      }
    }
  };
}

function elCol() {
  return {
    restrict: 'E',
    transclude: true,
    scope: { span: '@', offset: '@', xs: '@', md: '@', md: '@', md: '@' },
    template: `<div class="el-col" ng-class="['el-col-' + span,
      offset ? 'el-col-offset-' + offset : '',
      xs ? 'el-col-xs-' + xs : '',
      sm ? 'el-col-sm-' + sm : '',
      md ? 'el-col-md-' + md : '',
      xl ? 'el-col-xl-' + xl : ''
    ]" ng-transclude></div>`,
    link: function (scope, element) {
      const gutter = scope.$parent.$parent.gutter
      if (gutter) {
        element[0].children[0].style = `padding-right: ${gutter / 2}px;padding-left: ${gutter / 2}px`;
      }
    }
  };
}

/**
 * 
 * @param {*} $document 
 * @param {*} $timeout 
 * @returns Dropdown 下拉菜单
 */
function elDropdown($timeout) {
  return {
    restrict: 'E',
    transclude: true, // 启用内容嵌入
    scope: {
      options: '=',      // 菜单项数据源
      selected: '=?',    // 当前选中项
      trigger: '@',       // 触发方式 (click/hover)
      placement: '@',    // 菜单位置 (bottom/top)
      onSelect: '&'      // 选择回调
    },
    templateUrl: './component/el-dropdown/dropdown.html',
    controller: function ($scope, $element) {
      // 状态控制
      $scope.isOpen = false;
      const menu = $element[0].querySelector('.el-dropdown-menu');
      let hoverTimer;
      let hoverTimerOver;

      // 触发逻辑
      $scope.toggleMenu = function () {
        if ($scope.trigger === 'click') {
          $scope.isOpen = !$scope.isOpen;
          if ($scope.isOpen) calcPosition();
        }
      };

      // 控制清空按钮关闭
      $scope.onMouseleave = function () {
        $timeout.cancel(hoverTimerOver)
        $timeout.cancel(hoverTimer)
        hoverTimerOver = $timeout(function () {
          $scope.isOpen = false;
        }, 300)
      }

      // 悬停触发
      $scope.handleMouseEnter = function () {
        calcPosition();
        $timeout.cancel(hoverTimerOver)
        $timeout.cancel(hoverTimer)
        if ($scope.trigger === 'hover') {
          hoverTimer = $timeout(function () {
            $scope.isOpen = true;
          }, 300)
        }
      };

      // 位置计算
      const calcPosition = function () {
        $timeout(function () { // 等待DOM更新
          const triggerRect = $element[0].querySelector('.el-dropdown__trigger').getBoundingClientRect();
          menu.style = `top: ${triggerRect.height - 5}px;
          position: absolute;z-index: 2003;display: inline-block;white-space: nowrap;`
        }, 100);
      };

      // 关闭检测
      $scope.select = function (item) {
        $scope.isOpen = false;
        $scope.onSelect({ $item: item })
      }
    }
  };
}

/**
 * 
 * @returns Breadcrumb 面包屑
 */
function elBreadcrumb() {
  return {
    restrict: 'E',
    transclude: true,
    template: `
      <div class="el-breadcrumb" aria-label="Breadcrumb" role="navigation">
        <div ng-transclude></div>
      </div>
    `,
    controller: function ($scope, $attrs) {
      this.separator = $attrs.separator || '/';
      this.separatorClass = $attrs.separatorClass || '';
      console.log($attrs);
    }
  };
}

function elBreadcrumbItem() {
  return {
    restrict: 'E',
    require: '^elBreadcrumb',
    transclude: true,
    scope: {
      to: '@'
    },
    template: `
      <span class="el-breadcrumb__item">
        <span class="el-breadcrumb__inner" ng-class="{ 'is-link': current }" ng-transclude>
        </span>
        <span ng-if="!separatorClass" role="presentation" class="el-breadcrumb__separator">/</span>
        <i ng-if="separatorClass" class="el-breadcrumb__separator {{ separatorClass }}"></i>
      </span>
    `,
    link: function (scope, element, attrs, breadcrumbCtrl) {
      scope.to = {}; // 设置默认值

      if (attrs.to && typeof attrs.to === 'string') {
        try {
          // 步骤 2：修复字符串格式
          const fixedStr = attrs.to
            .replace(/'/g, '"')          // 单引号 → 双引号
            .replace(/(\w+):/g, '"$1":'); // 键名添加双引号

          // 步骤 3：安全解析
          scope.to = JSON.parse(fixedStr);
        } catch (e) {
          console.error('解析失败:', e);
        }
      } else {
        console.warn('attrs.to 为空或非字符串');
      }
      console.log(breadcrumbCtrl);
      scope.current = scope.to.path === breadcrumbCtrl.separator;
      scope.separatorClass = breadcrumbCtrl.separatorClass
    }
  };
}

/**
 * 
 * @param {*} $timeout 
 * @param {*} $compile 
 * @returns 卡片
 */
function elCard($timeout, $compile) {
  return {
    restrict: 'E',
    transclude: {
      header: '?header',  // ? 表示可选
      content: '?content',  // ? 表示可选
    },
    scope: {
      header: '@',
      shadow: '@'
    },
    templateUrl: './component/el-card/card.html',
    link: function (scope, element, attrs, ctrl, transclude) {
      transclude(function (clone, transcludeScope) {
        const targetBody = angular.element(element[0].querySelector('.el-card__body')); // 改为指令内部查找
        const targetHeader = angular.element(element[0].querySelector('.el-card__header'));

        // 批量编译+插入（减少 DOM 操作次数）
        const compiledNodes = Array.from(clone)
          .filter(function (node) { return node.nodeType === Node.ELEMENT_NODE })
          .map(function (node) {
            const compiled = $compile(node)(transcludeScope);
            return { node, compiled };
          });

        compiledNodes.forEach(function ({ node, compiled }) {
          switch (node.localName) {
            case 'content':
              targetBody.append(compiled);
              break;
            case 'header':
              targetHeader.append(compiled);
              break;
            default:  // 未匹配的节点处理
              element.append(compiled); // 或按业务需求处理
          }
        });
      })
      $timeout(function () {
        const cardHeader = element[0].querySelector('.el-card__header')
        if (!cardHeader.children.length) {
          cardHeader.style = 'display: none;'
        }
      })
    }
  };
}

/**
 * 
 * @returns 布局
 */
function elContainer() {
  return {
    restrict: 'E',
    transclude: true,
    template: `
      <section class="el-container" ng-class="{ 'is-vertical': direction === 'vertical' }" ng-transclude>
      </section>
    `,
    scope: {
      direction: '@' // 支持 horizontal/vertical 布局方向
    }
  };
}

function elHeader() {
  return {
    restrict: 'E',
    transclude: true,
    template: `
      <header class="el-header" ng-style="{ height: height }" ng-transclude>
      </header>
    `,
    scope: {
      height: '@' // 自定义高度，默认 60px
    },
    link: function (scope) {
      scope.height = scope.height || '60px';
    }
  };
}

function elAside() {
  return {
    restrict: 'E',
    transclude: true,
    template: `
      <aside class="el-aside" ng-style="{ width: width }" ng-transclude>
      </aside>
    `,
    scope: {
      width: '@', // 侧边栏宽度，默认 200px
    },
    link: function (scope) {
      scope.width = scope.width || '200px';
    }
  };
}

function elMain() {
  return {
    restrict: 'E',
    transclude: true,
    template: '<main class="el-main" style="height: calc(100vh - 58px);" ng-transclude></main>'
  };
}

function elFooter() {
  return {
    restrict: 'E',
    transclude: true,
    template: `
      <footer class="el-footer" ng-style="{ height: height }" ng-transclude>
      </footer>
    `,
    scope: {
      height: '@' // 默认高度 60px
    },
    link: function (scope) {
      scope.height = scope.height || '60px';
    }
  };
}

/**
 * 
 * @returns Cascader 级联选择器
 */
function elCascader() {
  return {
    restrict: 'E',
    templateUrl: './component/el-cascader/cascader.html',
    scope: {
      options: '=',
      onChange: '&',
      size: '@'
    },
    controller: ['$scope', '$element', '$timeout', function ($scope, $element, $timeout) {
      // 状态管理
      $scope.menuVisible = false;
      $scope.menuLevels = [];
      $scope.selectedLabel = '';
      $scope.selectedValues = [];
      $scope.menuWidth = 180;

      // 菜单显隐切换（修复事件冒泡）
      $scope.toggleMenu = function (event) {
        calcPosition()
        event.stopPropagation();
        $scope.menuVisible = !$scope.menuVisible;
        if ($scope.menuVisible) loadLevel(0);
      };

      // 位置计算
      const calcPosition = function () {
        $timeout(function () { // 等待DOM更新
          const triggerRect = $element[0].querySelector('.el-input').getBoundingClientRect();
          const dom = $element[0].querySelector('.el-cascader__dropdown');
          dom.style = `top: ${triggerRect.height}px;left: 0;
          position: absolute;z-index: 2003;display: inline-block;white-space: nowrap;`
        }, 100);
      };

      // 动态加载层级数据
      function loadLevel(levelIndex, parentItem) {
        var data = levelIndex === 0 ?
          $scope.options :
          (parentItem ? parentItem.children : []);

        $scope.menuLevels[levelIndex] = data;
        $scope.menuLevels.length = levelIndex + 1;
        $scope.menuWidth = 180 * $scope.menuLevels.length;
      }

      // 选项选中逻辑（支持异步加载）
      $scope.selectItem = function (item, levelIndex, event) {
        event.stopPropagation();

        if (item.disabled) return;

        // 更新选中值
        $scope.selectedValues[levelIndex] = item.value;
        $scope.selectedValues.splice(levelIndex + 1);
        $scope.onChange({ value: $scope.selectedValues })

        // 异步加载子级（示例）
        if (item.children && item.children.length) {
          loadLevel(levelIndex + 1, item);
        } else {
          $timeout(function () {
            $scope.menuVisible = false;
            updateDisplayLabel();
          }, 100);
        }
      };

      // 更新显示文本
      function updateDisplayLabel() {
        var labels = [];
        var current = $scope.options;

        $scope.selectedValues.forEach(function (val) {
          var item = current.find(function (it) { return it.value === val });
          labels.push(item.label);
          current = item.children || [];
        });

        $scope.selectedLabel = labels.join(' / ');
      }

      // 点击外部关闭菜单
      angular.element(document).on('click', function (event) {
        if (!$scope.menuVisible) return;
        if (!$element[0].contains(event.target)) {
          $scope.$apply(function () { $scope.menuVisible = false; });
        }
      });
    }]
  };
}

/**
 * 
 * @returns 进度条
 */
function elProgress() {
  return {
    restrict: 'E',
    templateUrl: './component/el-progress/progress.html',
    scope: {
      percentage: '=',
      strokeWidth: '@',
      showText: '@?',
      textInside: '@?',
      status: '@',
      color: '@',
      textColor: '@'
    },
    controller: ['$scope', function ($scope) {
      // 进度边界控制
      $scope.$watch('percentage', function (val) {
        if (val > 100) $scope.percentage = 100;
        if (val < 0) $scope.percentage = 0;
      });
    }],
    link: function (scope) {
      // 设置默认值
      scope.showText = scope.hasOwnProperty('showText') ?
        scope.showText !== 'false' : true;  // 处理字符串 "false" 转布尔值
      scope.textInside = scope.textInside || false;
    }
  };
}

/**
 * 
 * @returns Badge 标记
 */
function elBadge() {
  return {
    restrict: 'E',
    scope: {
      value: '@',       // 显示值（支持数字/字符串）
      max: '@?',       // 最大值（可选，默认 99）
      isDot: '@?',     // 是否显示为圆点（可选，默认 false）
      type: '@?'       // 类型（primary/success/warning/danger，默认 primary）
    },
    transclude: true,  // 支持内容投影
    template: `
      <div class="el-badge">
        <ng-transclude></ng-transclude>
        <span 
          class="el-badge__content"
          ng-class="[ !isDot ? 'is-fixed' : '', isDot ? 'is-dot' : '' , type ? 'el-badge__content--' + type : '']"
          ng-show="showBadge">
          {{ isDot === 'true' ? '' : displayValue }}
        </span>
      </div>
    `,
    link: function (scope) {
      // 最大值处理（默认99）
      const max = parseInt(scope.max) || 99;

      // 动态计算显示值
      scope.$watch('value', function (newVal) {
        if (scope.isDot === 'true') return;

        const numVal = parseInt(newVal) || 0;
        scope.displayValue = numVal > max ? max + '+' : numVal;
        scope.showBadge = numVal > 0;
      });
    }
  };
}

/**
 * 
 * @param {*} $interval 
 * @returns Carousel 走马灯
 */
function elCarousel($interval) {
  return {
    restrict: 'E',
    transclude: true,
    scope: {
      autoplay: '@',
      interval: '@',
      arrow: '@',
      type: '@',
      height: '@',
      indicator: '@',
      activeIndex: '='
    },
    templateUrl: './component/el-carousel/carousel.html',
    controller: function ($scope) {
      const vm = this;
      vm.items = [];
      // $scope.activeIndex = 0;

      vm.getActiveIndex = () => $scope.activeIndex;

      vm.addItem = function (item) {
        item.index = this.items.length;
        vm.items.push(item);
        $scope.items = vm.items;
      };
    },
    link: function (scope, element, attrs) {
      scope.containerHeight = scope.height || '300px';
      scope.showArrow = false
      scope.arrow = scope.arrow || 'hover'
      scope.position = 'prev'
      let autoplayTimer;

      // 切换方法
      scope.prev = function () {
        scope.position = 'prev'
        scope.activeIndex = (scope.activeIndex === 0)
          ? scope.items.length - 1
          : scope.activeIndex - 1;
      };

      scope.next = function () {
        scope.position = 'next'
        scope.activeIndex = (scope.activeIndex + 1) % scope.items.length;
      };

      scope.handleMouseEnter = function () {
        if (scope.arrow === 'hover')
          scope.showArrow = true
      }
      scope.onMouseleave = function () {
        if (scope.arrow === 'hover')
          scope.showArrow = false
      }

      // 自动播放
      if (scope.autoplay === 'true') {
        const interval = parseInt(scope.interval) || 3000;
        autoplayTimer = $interval(scope.next, interval);
      }

      // 清理
      element.on('$destroy', function () {
        $interval.cancel(autoplayTimer);
      });
    }
  };
}

function elCarouselItem() {
  return {
    restrict: 'E',
    require: '^^elCarousel',
    transclude: true,
    template: '<div ng-transclude></div>',
    link: function (scope, element, attrs, carouselCtrl) {
      // 注册到父控制器并记录自身索引
      const item = {
        element: element,
        index: carouselCtrl.items.length
      };
      carouselCtrl.addItem(item);

      // 监听父控制器的 activeIndex
      scope.$watch(
        () => carouselCtrl.getActiveIndex(),
        (parentIndex) => {
          const currentIndex = item.index;
          const total = 3; // 总卡片数
          const parentWidth = element[0].offsetParent.clientWidth;
          // 核心循环逻辑：通过模运算实现环形索引
          const delta = (currentIndex - parentIndex + total) % total;

          // 方向控制：从右向左平移（使用正方向偏移）
          const offsetValue = delta * (scope.$parent.position === 'prev' ? parentWidth : -parentWidth);

          element.css('transform', `translateX(${offsetValue}px)`);

          // 激活状态控制
          element[0].classList.toggle('is-active', delta === 0);
          element[0].classList.toggle('is-animating', delta === 0);
        }
      );
    }
  };
}

/**
 * 
 * @param {*} $document 
 * @param {*} $window 
 * @param {*} $timeout 
 * @returns Popconfirm 气泡确认框
 */
function elPopconfirm($document, $timeout) {
  return {
    restrict: 'E',
    transclude: {
      'reference': '?slotReference'
    },
    scope: {
      title: '@',
      confirmButtonText: '@',
      cancelButtonText: '@',
      confirmButtonType: '@',
      cancelButtonType: '@',
      icon: '@',
      iconColor: '@',
      hideIcon: '@',
      onConfirm: '&',
      onCancel: '&'
    },
    template: `
    <div class="el-popconfirm-wrapper">
      <div class="el-popconfirm__reference" ng-transclude="reference"></div>
      <div class="el-popover el-popper" ng-if="visible">
        <div class="el-popconfirm">
          <div class="el-popconfirm__arrow"></div>
          <div class="el-popconfirm__main">
            <i ng-if="hideIcon === 'true'" class="{{icon}} el-popconfirm__icon" style="color: {{iconColor}}"></i>
            <p class="el-popconfirm__message">{{title}}</p>
          </div>
          <div class="el-popconfirm__action">
            <el-button type="{{ cancelButtonType || 'text' }}" size="mini" ng-click="handleCancel()">{{cancelButtonText || '取消'}}</el-button>
            <el-button type="{{ confirmButtonType || 'primary' }}" size="mini" ng-click="handleConfirm()">{{confirmButtonText || '确定'}}</el-button>
          </div>
        </div>
      </div>
    </div>
    `,
    link: function(scope, element) {
      let trigger;

      // 延迟获取触发元素
      $timeout(function() {
        const trigger = element[0].querySelector('.el-popconfirm__reference');
        // trigger = referenceDiv.children()[0];
        
        // 绑定点击事件
        angular.element(trigger).on('click', function(e) {
          e.stopPropagation();
          scope.visible = !scope.visible;
          scope.$apply();
        });
      });

      // 确认/取消处理
      scope.handleConfirm = function() {
        scope.onConfirm();
        scope.visible = false;
      };
      scope.handleCancel = function() {
        scope.onCancel();
        scope.visible = false;
      };

      // 清理
      element.on('$destroy', function() {
        angular.element(trigger).off('click');
      });
    }
  };
}